﻿//理论上来讲所有近战可以写成一个类，播放不同动画即可，但动画字典一开始设计不合理，一对一
using Assets.Scripts.DL.Consts;
using Assets.Scripts.DL.Mgrs;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem.XR;
using static PlayerStateEnum;
/// <summary>
/// 3段近战
/// </summary>
public class PlayerMelee : PlayerBaseState {
	readonly PlayerStateEnum[] _handStates;
	readonly PlayerStateEnum[] _grdWponStates;
	readonly PlayerStateEnum[] _airWponStates;
	PlayerStateEnum[] _curStates;
	string[] _curAudio;
	readonly bool[] _damageSend;
	readonly bool[] _animStart;
	int _curAtkIndex = 0;//第几段
	int _firstIndex;
	bool _preInput;//预输入

	readonly string[] _swdAudio;
	readonly string[] _punchAudio;


	Vector2 _atkOffset;
	float _range;
	int _damage;
	Timer _lastAtkTimer = new();
	public PlayerMelee(PlayerController controller, PlayerStateEnum stateName, State<PlayerStateEnum> superFSM, StateFactory<PlayerStateEnum> factory) : base(controller, stateName, superFSM, factory) {
		AddConditionToSelf(() => controller.HandWeaponInput);


		_handStates = new PlayerStateEnum[] { Punch1, Punch2, Punch3 };
		_grdWponStates = new PlayerStateEnum[] { GroundSwd1, GroundSwd2, GroundSwd3 };
		_airWponStates = new PlayerStateEnum[] { AirSwd1, AirSwd2 };
		_swdAudio = new string[] { AudioStr.PlayerSwdAtk1Audio, AudioStr.PlayerSwdAtk2Audio, AudioStr.PlayerSwdAtk3Audio };
		_punchAudio = new string[] { AudioStr.PlayerHandAtk1Audio, AudioStr.PlayerHandAtk2Audio, AudioStr.PlayerHandAtk3Audio };
		_damageSend = new bool[_handStates.Length];
		_animStart = new bool[_handStates.Length];

		AddNewTransition(GrdMelee, () => _curAtkIndex == _handStates.Length && controller.HandWeaponInput);
	}

	public override void Enter() {
		_curStates = _controller.StateData.IsCurHandAtk ? _handStates :
			(_controller.IsOnGround ? _grdWponStates : _airWponStates);
		if (_controller.StateData.IsCurHandAtk) {
			_atkOffset = _controller.ConfigData.PunchOff;
			_range = _controller.ConfigData.PunchRad;
			_damage = _controller.ConfigData.PunchDamage;
			_curAudio = _punchAudio;
		}
		else {
			_atkOffset = _controller.ConfigData.GrdSwdAtkOff;
			_range = _controller.ConfigData.GrdSwdRad;
			_damage = _controller.ConfigData.SwdDamage + _controller.StateData.SwordExAtk;
			_curAudio = _swdAudio;
		}

		if (_curAtkIndex >= _curStates.Length || _lastAtkTimer.Elapsed > _controller.ConfigData.TwoAtkGap) {
			_curAtkIndex = 0;
			_lastAtkTimer.Reset();
		}

		//Debug.Log($"{_lastAtkTimer.Elapsed}");
		_firstIndex = _curAtkIndex;
		//Debug.Log(_curAtkIndex);
		_controller.PlayAnim(_curStates[_curAtkIndex]);
		AudioManager.Play(_controller.Effect, _curAudio[_curAtkIndex]);
		_animStart[_curAtkIndex] = true;
		Array.Fill(_damageSend, false);
		Array.Fill(_animStart, false);
		_controller.Velocity = Vector2.zero;
		_preInput = false;
	}

	public override void Update() {
		base.Update();
		//Debug.Log(_curAtkIndex);
		if (!_damageSend[_firstIndex]) {
			CheckDamage(ref _damageSend[_firstIndex]);
		}
		Atk();
		if (_controller.IsOnGround)
			_controller.Velocity = new Vector2(_controller.XInput * _controller.ConfigData.GrdAtkXmoveSpeed, 0);
	}

	public override void Exit() {
	}

	void Atk() {
		if (_controller.IsAnimPlayAt(_controller.ConfigData.PreInputNormalizeTime) && !_preInput)
			_preInput = _controller.HandWeaponInput;
		if (_curAtkIndex == 0 || _curAtkIndex == _curStates.Length)
			return;
		var tmp = true;
		var lastAtkIndex = _curAtkIndex - 1;
		//下一段
		if (_damageSend[lastAtkIndex] && _preInput && _controller.IsAnimPlayAt(_controller.ConfigData.AtkAnimChangeNormalizeTime) && !_animStart[_curAtkIndex]) {
			_controller.PlayAnim(_curStates[_curAtkIndex]);
			AudioManager.Play(_controller.Effect, _curAudio[_curAtkIndex]);
			_animStart[_curAtkIndex] = true;
			_preInput = false;
			tmp = false;
		}
		if (_animStart[_curAtkIndex] && tmp && !_damageSend[_curAtkIndex]) {
			CheckDamage(ref _damageSend[_curAtkIndex]);
		}
	}

	void CheckDamage(ref bool dmgSend) {
		if (_controller.IsAnimPlayAt(0.65f)) {
			//Debug.Log("SendDamage");
			_controller.CheckAtk(_atkOffset, _range, _damage);
			dmgSend = true;
			_curAtkIndex++;
		}
	}
	//bool IsSwdAtk => _controller.HandWeaponInput && !_controller.StateData;
	bool IsRunPunch => _controller.HandWeaponInput && _controller.StateData.IsCurHandAtk && !IsZero(_controller.XInput);
}